package com.ltu.payment;

import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.DocumentException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONObject;
import com.ltu.base.State;
import com.ltu.domain.mp_entity.PayRecord;
import com.ltu.domain.mp_entity.customize.CompanyEntity;
import com.ltu.domain.mp_entity.customize.RefunRecordEntity;
import com.ltu.mapper.PayRecordMapper;
import com.ltu.payment.config.WxAppPayConfig;
import com.ltu.payment.util.SignUtils;
import com.ltu.payment.util.XmlUtils;
import com.ltu.util.common.StrUtils;
import com.ltu.util.exception.ApiException;
import com.ltu.util.http.HttpPostUtil;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.CreateRequest;

import lombok.extern.slf4j.Slf4j;


/**  
 * @Description: 服务商模式支付
 */
@Slf4j
@Component
public class WxPayServices2 {
	@Value("${payInfo.test}")
    private Integer PayTest = 1;
	@Value("${wx.pay.notifyUrl}")
    private String notifyUrl;
	@Value("${wx.pay.appid}")
	private String appId;
	@Value("${wx.pay.subAppId}")
	private String subAppId;
	@Value("${wx.pay.mchId}")
	private String mchId;
	@Value("${wx.pay.subMchId}")
	private String subMchId;
	@Value("${wx.pay.mchKey}")
	private String serviceMchKey;
//	@Value("${wx.pay.subMchKey}")
//	private String subMchKey;
//	private final static String   WXHost = "https://api.mch.weixin.qq.com";
	@Autowired
	private  RSAAutoCertificateConfig wxFwsRSAConfig;
	@Autowired
	PayRecordMapper  payRecordMapper;
//	  @Autowired
//	    private  WxPayProperties wxPayProperties;
	
	/**
	 * 服务商模式
	 * @param payRecord
	 * @param openid
	 * @param ip
	 * @return
	 */
	public  JSONObject   placeOrder(PayRecord payRecord,String openid,String ip){
		Integer total_fee = payRecord.getPayMoney();
		SortedMap<String,Object>   param=new TreeMap<>();
		param.put("appid",appId);  //服务商的APPid
		param.put("mch_id",mchId);		// 服务商的商户ID
		param.put("sub_appid",subAppId);  //小程序appId
		param.put("sub_mch_id",subMchId); //子商户
		String nonce_str= String.valueOf(new Date().getTime());
		param.put("nonce_str", nonce_str);
		param.put("body", payRecord.getPayName());//商品描述
		param.put("out_trade_no",payRecord.getOrderNo());//订单号(PAY*)
		param.put("total_fee", ""+total_fee);//交易金额  单位：分
		if(PayTest==1) 
			param.put("total_fee", 1);//交易金额 单位：分
		param.put("spbill_create_ip", ip);
		param.put("notify_url", notifyUrl);//回调地址
	    param.put("trade_type", "JSAPI");
	    param.put("sub_openid", openid);
	     //转QuseryString字符串
	   String xmlStr=  XmlUtils.paramSort(param,serviceMchKey);  
	   
	   System.out.println("\n 请求的xml参数为：" + xmlStr);
		String resultStr =	HttpPostUtil.sendPost(WxAppPayConfig.WxPayMent, xmlStr);
		
		log.info("本次下单结果："+resultStr);
		if(StringUtils.isBlank(resultStr)){
			throw new ApiException("请求异常");
		}
		JSONObject	  resultMap=new JSONObject();	
		Map<String,String> resultMap1=null;
			 try {
				resultMap1=	XmlUtils.toMap(resultStr.getBytes(), "utf-8");
			
			 JSONObject result=(JSONObject) JSONObject.toJSON(resultMap1);
			
			StringBuilder subStr = new StringBuilder("");
			if (!result.get("return_code").equals("SUCCESS")) {
				subStr.append("\n 通信失败,");
				subStr.append(" \n 请求状态：");
				subStr.append(result.get("return_code"));
				subStr.append("\t ,错误描述：");
				subStr.append(result.get("return_msg"));
				log.error(subStr.toString());
				payRecord.setIsExpire((byte)1);//失效
				payRecord.setStatus((byte) -1);//错误状态
				payRecord.setStatusDesc(subStr.toString());
				throw new ApiException(State.CODE_FAILED,subStr.toString());
			} else {
				if (result.get("result_code").equals("SUCCESS")) {
					  String prepay_id = result.getString("prepay_id");
					  resultMap=SignUtils.createPayParams(subAppId, nonce_str, nonce_str, prepay_id,serviceMchKey);
					 //拉起收银成功状态改为正在支付
					  payRecord.setStatus((byte) 2);
					  payRecord.setStatusDesc("拉起收银台成功,正在支付...");
				} else {
					log.error(resultStr);    
					subStr.append("\n 拉起微信官方支付失败：");
					subStr.append(result.getString("result_code"));
					subStr.append(" \n 通信状态：");
					subStr.append(result.get("return_code"));
					subStr.append("\t ,通信描述：");
					subStr.append(result.get("return_msg"));
					subStr.append("\t ,错误码：");
					subStr.append(result.get("err_code"));
					subStr.append("\t ,错误描述：");
					subStr.append(result.get("return_msg"));
					subStr.append("\t ,系统错误描述：");
					subStr.append(result.get("err_code_des"));
					log.error(" 拉起微信官方支付失败：\n" + resultStr);
					payRecord.setIsExpire((byte)1);//失效
					payRecord.setStatus((byte) -1);//错误状态
					payRecord.setStatusDesc(subStr.toString());
					throw new ApiException(State.CODE_FAILED,subStr.toString());
				}
			}
			 } catch (DocumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
			}finally{
				payRecordMapper.updateById(payRecord);
			}
		 return resultMap;
	}
	
	/**
	 * 
	 * @date 2019年2月25日
	 * @author 若尘
	 * @Description 服务商模式退款
	 * @param mchId
	 * @param payKey =  @see WxAppPayConfig.WxMchKey
	 * @param certFileName 证书文件名称
	 * @param refunRecord
	 *            void
	 */
	public Boolean sendRefund(RefunRecordEntity refunRecord) {
		Boolean  flag = false;
		JSONObject param = new JSONObject();
		param.put("sub_mchid", subMchId);
		param.put("transaction_id", refunRecord.getPayCode());// "mfb2018122818051143"
//		param.put("notify_url", refunRecord.getPayCode());// "mfb2018122818051143"
//		param.put("sub_appid", subAppId);
//		param.put("sp_appid", appId);
		param.put("out_refund_no", refunRecord.getOutRefundNo());
		param.put("reason", "客户申请退款");
		
		JSONObject amount = new JSONObject();
		amount.put("refund", refunRecord.getRefundMoney());
		amount.put("total",  refunRecord.getTotalMoney());
		amount.put("currency", "CNY");
		param.put("amount", amount);
//		String xmlStr = XmlUtils.paramSort(param,c.getMchKeyApi2());
		System.out.println("\n 服务商模式退款，请求参数：" + param.toJSONString());
		String result = "";
		JSONObject resultMap = null;

//		String userDir = System.getProperties().getProperty("user.dir").concat(File.separator).concat("cert");
//		String path = userDir.concat(File.separator).concat(c.getMchId() +".p12");
		try {
			String  str  =  param.toJSONString();
//			
//			RefundService wxRefundRest = new RefundService.Builder().config(wxFwsRSAConfig).build();
//			wxRefundRest.create(null)
			URI  url = new URI( WxAppPayConfig.REFUND2);
			
			String authorization= wxFwsRSAConfig.createCredential().getAuthorization(url, "POST",str);
//返回结果：{"amount":{"currency":"CNY","discount_refund":0,"from":[],"payer_refund":1,"payer_total":1,"refund":1,"refund_fee":0,"settlement_refund":1,"settlement_total":1,"total":1},"channel":"ORIGINAL","create_time":"2025-01-13T12:31:21+08:00","funds_account":"UNAVAILABLE","out_refund_no":"D20250110163332847000047080074","out_trade_no":"D20250110163332847000047080074","promotion_detail":[],"refund_id":"50301601972025011386092819191","status":"PROCESSING","transaction_id":"4200002454202501108829500856","user_received_account":"支付用户零钱"}
			result = HttpPostUtil.sendRawPost(WxAppPayConfig.REFUND2,str , authorization);
			System.out.println("返回结果：" + result.toString());
			resultMap = JSONObject.parseObject(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
			// 退款状态0=退款失败1=退款成功2=退款中3=等待审核4=通过审核或者无需审核5=申请退款异常
			StringBuilder subStr = new StringBuilder("");

			if (resultMap.get("status").equals("PROCESSING") ||resultMap.get("status").equals("SUCCESS")  ) {
				refunRecord.setStatus(2);
				refunRecord.setRefundRemark("申请退款成功,退款处理中");
				refunRecord.setStatusDescription("申请退款成功,退款处理中");
				refunRecord.setRefundId(resultMap.getString("refund_id"));
				flag = true;
			}else{
				refunRecord.setStatus(5);
				subStr.append("\n 退款失败,退款状态码为：");
				subStr.append(resultMap.get("status"));
				subStr.append("\t ,错误描述：");
				subStr.append(resultMap.toJSONString());
				refunRecord.setRefundRemark(subStr.toString());
				refunRecord.setStatusDescription(subStr.toString());
				refunRecord.setRefundId(resultMap.getString("refund_id"));
			}
			
		return flag;

	}
	
	/**
	 * 微信支付签名
	 * @date 2019年1月22日
	 * @author 若尘
	 * @Description 签名=排序+加密
	 * @param json
	 * @return
	 * String
	 */
	public  void  paramSort(JSONObject json,String signKey){
//		String result = "";
		StringBuilder result=new StringBuilder();
		String[] arr = new String[json.keySet().size()];
		int len = arr.length;
		json.keySet().toArray(arr);
		Arrays.sort(arr);//QueryString排序
		for (int i = 0; i < len; i++) {
			result.append(arr[i]); 
			result.append("="); 
			result.append(json.get(arr[i])); 
			if (i < len - 1) {
				result.append("&"); 
//				result += arr[i] + "=" + json.get(arr[i]) + "&";
			} 
		}
		System.out.println("\n 排好序的字符串" + result);
//		result += CommonDir.key;
		result.append(signKey);
		System.out.println("\n 等待加密的字符串：" + result);
		String sign = DigestUtils.md5Hex(result.toString()).toUpperCase();
		
		System.out.println("\n Md5加密后且转为大写的签名字符串：" + sign);
		json.put("sign", sign);
		
	}
	
}

